/*******************************************************************************
 * Copyright (c) 2006 CEA List.
 * All rights reserved. This program and the accompanying materials
 * are made available under the terms of the Eclipse Public License v1.0
 * which accompanies this distribution, and is available at
 * http://www.eclipse.org/legal/epl-v10.html
 *
 * Contributors:
 *     CEA List - initial API and implementation
 *******************************************************************************/
package com.cea.papyrus.diagram.component.figure;

import org.eclipse.draw2d.ColorConstants;
import org.eclipse.draw2d.FigureUtilities;
import org.eclipse.draw2d.FreeformLayer;
import org.eclipse.draw2d.FreeformLayout;
import org.eclipse.draw2d.FreeformViewport;
import org.eclipse.draw2d.Graphics;
import org.eclipse.draw2d.IFigure;
import org.eclipse.draw2d.Label;
import org.eclipse.draw2d.LineBorder;
import org.eclipse.draw2d.ScrollPane;
import org.eclipse.draw2d.StackLayout;
import org.eclipse.draw2d.ToolbarLayout;
import org.eclipse.draw2d.geometry.Dimension;
import org.eclipse.draw2d.geometry.Rectangle;
import org.eclipse.swt.SWT;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.FontData;
import org.eclipse.swt.graphics.RGB;
import org.eclipse.uml2.uml.Element;

import com.cea.papyrus.core.PapyrusPlugin;
import com.cea.papyrus.core.figures.NodeFigure;
import com.cea.papyrus.core.helper.ModelerHelper;
import com.cea.papyrus.core.utils.Debug;
import com.cea.papyrus.diagraminterchange2.di2.GraphElement;


/**
 * Defines the view of a component
 * 
 * @author Agnes Lanusse
 * @since  April 07
 */
public class ComponentFigure extends NodeFigure {
	/**
	 * 
	 */
	private int debugChannel=6;
	
	/**
	 * 
	 */
	int [] dashes= new int[10];
	
	/**
	 * 
	 */
	protected boolean extern= false;
	protected boolean isContainer=true;
	protected boolean isNameUnderlined=false;
	/**
	 * 
	 */
	public static Color classColor = PapyrusPlugin.colorManager.get(new RGB(227,221,239));
	
	/**
	 * 
	 */
	public static Color classBorderColor= PapyrusPlugin.colorManager.get(new RGB(166,157,183));

	/**
	 * 
	 */
	protected UMLComponentHeaderFigure headerFigure; //head of the component
	
	/**
	 * 
	 */
	protected UMLComponentContentFigure contentFigure = null;// content of the component

	/**
	 * 
	 */
	class UMLComponentHeaderFigure extends NodeFigure {
		//protected Rectangle myBounds;

		/**
		 * 
		 */
		public UMLComponentHeaderFigure() {
			ToolbarLayout layout = new ToolbarLayout();

			setLayoutManager(layout);
			layout.setSpacing(2);
			setOpaque(true); // non-transparent figure
			setBorder( new LineBorder(ColorConstants.black));
			setBackgroundColor(ColorConstants.yellow);	

		}

		/**
		 * setBound is called to resize or move graphical Element by Eclipse
		 * In the case of this package we have to call setDimension Before.
		 * 
		 * @param rect coordinate of the contentPackage.
		 * 
		 * @see setDimension
		 */

		@Override
		public void setBounds(Rectangle rect) {

			int headerHeight = getNameLabel().getPreferredSize().height;
			int headerWidth  = rect.width;

			// Calculate height
			if (getStereotypesLabel() != null) {
				headerHeight = headerHeight +getStereotypesLabel().getPreferredSize().height+5;
			}
			if (getIconLabel() != null) {
				headerHeight = headerHeight + getIconLabel().getPreferredSize().height;
			}
			if (getQualifiedNameLabel() != null) {
				headerHeight = headerHeight + getQualifiedNameLabel().getPreferredSize().height+5;
			}
			Rectangle headerRect = new Rectangle();
			headerRect.setLocation(0, 0);
			headerRect.setSize(headerWidth, headerHeight);

			super.setBounds(headerRect);

			Debug.debug(this," bounds are : " +getBounds(), debugChannel);
		}	
		

		@Override
		public void refreshPresentation (String presentation, Element selection, GraphElement ge) {
			org.eclipse.swt.graphics.Image icon =PapyrusPlugin.getIconElement(selection);
			
			/* if the presentation is icon or icon with text, we can set the icon */
			if ( (icon != null) 
				&& (presentation.equals(ModelerHelper.ICON_STEREOTYPE_PRESENTATION)
					 || presentation.equals(ModelerHelper.TEXT_ICON_STEREOTYPE_PRESENTATION)) ) {
				this.setIcon(icon);
				if (iconLabel == null) {
					createIconLabel();
				}
				iconLabel.setIcon(icon);
				iconLabel.repaint();
				this.add(iconLabel,0);
				this.repaint();		
			}
			else if (presentation.equals(ModelerHelper.DEFAULT_PRESENTATION) 
					|| presentation.equals(ModelerHelper.TEXT_STEREOTYPE_PRESENTATION)) {
//				setIcon(PapyrusPlugin.getImage(PapyrusPlugin.UML_ICONS_16x16+"Component.gif"));
				setIcon(PapyrusPlugin.getImage(PapyrusPlugin.UML_ICONS_16x16+"Component.jpg"));
			}
			else {
				if (iconLabel != null) {
					iconLabel.setIcon(null);
					iconLabel.repaint();
					if (iconLabel.getParent() != null)	{
						this.remove(iconLabel);
					}
					this.repaint();
				}
			}
			return;
		}
	}

	/**
	 * display the content of the component
	 * *.
	 */
	class UMLComponentContentFigure extends NodeFigure  {

		/**
		 * 
		 */
		private IFigure pane;
		
		/**
		 * 
		 */
		protected ScrollPane scrollpane;

		/**
		 * 
		 */
		public UMLComponentContentFigure() {
			Debug.debug(this,"  Call UMLComponentContentFigure", debugChannel);

			// Set content layout
			setLayoutManager(new StackLayout());

			// Add pane for content
			pane = new FreeformLayer();
			pane.setLayoutManager(new FreeformLayout());

			// Add scrollpane
			ScrollPane scrollpane = new ScrollPane();
			scrollpane.setViewport(new FreeformViewport());
			scrollpane.setContents(pane);
			this.add(pane);

			// Set colors
			setBackgroundColor(headerFigure.getBackgroundColor());
			setBorder(new LineBorder(headerFigure.getBorderColor()));
			setOpaque(true);
		}

		/**
		 * 
		 * 
		 * @return 
		 */
		public IFigure getContentPane() {
			return pane;
		}

		/**
		 * setBound is called to resize or move graphical Element by Eclipse
		 * In the case of this package we have to call setDimension Before.
		 * 
		 * @param rect coordinate of the contentPackage.
		 * 
		 * @see setDimension
		 */

		@Override
		public void setBounds(Rectangle rect) {

			int contentHeight = 0;
			int contentWidth  = 0;

			// Father dimension
			int fatherHeight = getParent().getBounds().height;
			int fatherWidth  = getParent().getBounds().width;

			super.setBounds(new Rectangle(
					0
					, headerFigure.getSize().height
					, fatherWidth
					, fatherHeight-headerFigure.getSize().height));

			Debug.debug(this," bounds are : " +getBounds(), debugChannel);
		}
	}


	public ComponentFigure()
	{
		ToolbarLayout layout = new ToolbarLayout();
		setLayoutManager(layout);
		for (int i=0;i<10;i++) {
			dashes[i]=5;
		}

		headerFigure = new UMLComponentHeaderFigure();
		add(headerFigure);
		contentFigure =new UMLComponentContentFigure();
		add(contentFigure);	
		super.setBorder(null);
		setOpaque(false);
	}

	@Override
	public void setBorderColor(Color borderColor) {
		this.borderColor = borderColor;
		getHeader().setBorder(null);
		contentFigure.setBorder(null);


	}

	@Override
	public void paintBorder(Graphics graphics) {
		graphics.setForegroundColor(getBorderColor());
		if( extern){	
			graphics.setLineDash(dashes);
		}
		graphics.setLineWidth(1);

		graphics.drawRectangle(this.getBounds().x,
				this.getBounds().y,
				this.getBounds().width-1,
				this.getBounds().height-1);
		//draw line separator
		Rectangle rect = getHeader().getBounds();
		if( isContainer){
			graphics.drawLine(this.getBounds().x,
				this.getBounds().y+this.getHeadHeight(),
				this.getBounds().x+this.getBounds().width-1,
				this.getBounds().y+this.getHeadHeight());
		}
		
		if (isNameUnderlined) {
			graphics.setForegroundColor(ColorConstants.black);
			Rectangle rectLabel = getNameLabel().getBounds();
			Dimension labelSize=FigureUtilities.getTextExtents(getNameLabel().getText(), getNameLabel().getFont());
			graphics.drawLine(this.getBounds().x+rectLabel.width/2-labelSize.width/2,
					this.getBounds().y+rectLabel.height-2,
					this.getBounds().x+rectLabel.width/2+labelSize.width/2,
					this.getBounds().y+rectLabel.height-2);
			
		}
	}

	/**
	 * this method is used to display  dashes if the composite is extern.
	 * 
	 * @param value to set if the class is extern
	 */
	public void setExtern(boolean value){
		this.extern =value;
		this.repaint();
	}
	
	public void setNameUnderlined(boolean isNameUnderlined) {
		this.isNameUnderlined = isNameUnderlined;
		this.repaint();
	}
	
	public void setContainer(boolean value){
		this.isContainer =value;
		this.repaint();
	}
	/*
	 * (non-Javadoc)
	 * @see com.cea.papyrus.common.figures.AbstractElementFigure#setBackgroundColor(org.eclipse.swt.graphics.Color)
	 */

	@Override
	public void setBackgroundColor(Color backgroundColor) {

		super.setBackgroundColor(backgroundColor);
		headerFigure.setBackgroundColor(backgroundColor);
		contentFigure.setBackgroundColor(backgroundColor);
	}
	/*
	 * (non-Javadoc)
	 * @see com.cea.papyrus.common.figures.AbstractElementFigure#setFontColor(org.eclipse.swt.graphics.Color)
	 */

	@Override
	public void setFontColor(Color color) {
		this.fontColor=color;
		getHeader().setFontColor(color);
	}
	/*
	 * (non-Javadoc)
	 * @see com.cea.papyrus.common.figures.AbstractElementFigure#setForeGroundColor(org.eclipse.swt.graphics.Color)
	 */

	@Override
	public void setForeGroundColor(Color color) {
		super.setForeGroundColor(color);

	}
	
	/**
	 * setBound is called to resize or move graphical Element by Eclipse
	 * It call setBound of each subFigure.
	 * In the case of contentPackage we call setDimension
	 * 
	 * @param rect coordinate of the contentPackage.
	 * 
	 * @see setDimension
	 */

	@Override
	public void setBounds(Rectangle rect) {
		// Header
		headerFigure.setBounds(new Rectangle(rect));
		// Content
		contentFigure.setBounds(new Rectangle(rect));

		super.setBounds(new Rectangle(rect));

		Debug.debug(this," bounds are : " +getBounds(), debugChannel);
	}

	/**
	 * to obtain the header of the component figure.
	 * 
	 * @return IFigure the header
	 */
	public UMLComponentHeaderFigure getHeader() {
		return headerFigure;
	}

	/**
	 * 
	 * 
	 * @return 
	 */
	public IFigure getContentsPane(){
		return contentFigure.getContentPane();
	}

	/**
	 * 
	 * 
	 * @return 
	 */
	@Override
	protected boolean useLocalCoordinates(){return true;}

	/**
	 * 
	 * 
	 * @return 
	 */
	public int getHeadWitdh(){ return headerFigure.getPreferredSize().width;}
	
	/**
	 * 
	 * 
	 * @return 
	 */
	public int getHeadHeight(){ return headerFigure.getPreferredSize().height;}

	// Override method from AbstractElementFigure
	/**
	 * 
	 * 
	 * @return Returns the nameLabel.
	 */
	@Override
	public Label getNameLabel() {
		return headerFigure.getNameLabel();
	}
	
	/**
	 * 
	 * 
	 * @return Returns the qualifiedNameLabel.
	 */
	@Override
	public Label getQualifiedNameLabel() {
		return headerFigure.getQualifiedNameLabel();
	}
	
	/**
	 * 
	 * 
	 * @return Returns the nameLabel.
	 */
	@Override
	public Label getStereotypesLabel() {
		return headerFigure.getStereotypesLabel();
	}

	/**
	 * 
	 * 
	 * @param name 
	 */
	@Override
	public void setName( String name )
	{
		headerFigure.setName(name);
	}
	
	/**
	 * 
	 * 
	 * @param packageName 
	 */
	@Override
	public void setQualifiedName( String packageName )
	{
		headerFigure.setQualifiedName(packageName);
	}
	
	/**
	 * Set the stereotype value.
	 * If param is null, remove the label.
	 * 
	 * @param stereotypes 
	 */
	@Override
	public void setStereotypes( String stereotypes )
	{
		headerFigure.setStereotypes(stereotypes);
	}

	/**
	 * Refresh presentation of current figure
	 * with presentation specified in a GraphNode.
	 * 
	 * @param presentation 
	 * @param selection 
	 */
	@Override
	public void refreshPresentation(String presentation, Element selection,GraphElement ge) {
		headerFigure.refreshPresentation(presentation, selection,ge);
	//	contentFigure.refreshPresentation(presentation, selection, ge);
	}
	

	/**
	 * Refresh list of stereotypes of current EditPart if required
	 * either with or without the first stereotype.
	 * 
	 * @param presentation 
	 * @param hasIcon 
	 * @param hasShape 
	 * @param stereotypes 
	 */
	@Override
	public void refreshStereotypes(String stereotypes, String presentation, boolean hasIcon, boolean hasShape) {
		headerFigure.refreshStereotypes(stereotypes, presentation, hasIcon, hasShape);

	}

	/**
	 * 
	 * 
	 * @param b 
	 */
	public void setAbstract(boolean b){
		
		if (b) {
			FontData[] font={new FontData(getfigureFont(), getFontSize(), SWT.ITALIC|SWT.BOLD)};
			this.getNameLabel().setFont(PapyrusPlugin.fontManager.get(font));//italic
		} else {
			FontData[] font={new FontData(getfigureFont(), getFontSize(), SWT.BOLD)};
			this.getNameLabel().setFont( PapyrusPlugin.fontManager.get(font));
		}
	}
}

